package com.ncu.xrpc.proxy;

import cn.hutool.core.util.StrUtil;
import com.ncu.xrpc.ServiceDiscovery;
import com.ncu.xrpc.client.RpcClient;
import com.ncu.xrpc.entity.XRpcRequest;
import com.ncu.xrpc.entity.XRpcResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;

/**
 * Created by IntelliJ IDEA.
 * User: xiongwb
 * Date: 2021/9/11 21:02\
 * Describe: 创建代理对象
 */
@Slf4j
@Component
public class RpcProxy {

    //提供服务的 ip:port
    private String serviceAddress;

    //提供服务发现 服务
    @Autowired
    private ServiceDiscovery serviceDiscovery;
    public RpcProxy(){

    }

    public RpcProxy(String serviceAddress){this.serviceAddress = serviceAddress;}

    public RpcProxy(ServiceDiscovery serviceDiscovery){this.serviceDiscovery = serviceDiscovery;}

    //忽略警告信息   开始创建代理对象
    @SuppressWarnings("unchecked")
    public <T> T createProxy(Class<T> interfaceClass){
        return doCreateProxy(interfaceClass,"");
    }

    //真正开始创建代理信息
    @SuppressWarnings("unchecked")
    public <T> T doCreateProxy(Class<T> interfaceClass,String serviceVersion){
        InvocationHandler invocationHandler = new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //创建RPC请求
                XRpcRequest xRpcRequest = new XRpcRequest();

                //设置请求ID
                xRpcRequest.setRequestId(UUID.randomUUID().toString());

                //设置请求参数
                xRpcRequest.setArgs(args);

                //设置调用的方法名
                xRpcRequest.setMethodName(method.getName());

                //设置调用的方法参数类型
                xRpcRequest.setParameterTypes(method.getParameterTypes());

                //设置版本号
                xRpcRequest.setVersion(serviceVersion);

                //设置类名
                xRpcRequest.setClassName(method.getDeclaringClass().getName());


                //获取服务名
                String serviceName = interfaceClass.getName();

                //拼接完整服务名
                if (StrUtil.isNotEmpty(serviceVersion)) {
                    serviceName = serviceName + "-" + serviceVersion;
                }

                if(serviceDiscovery!=null) {

                    //获取服务ip:port
                    serviceAddress = serviceDiscovery.discover(serviceName);
                    log.info("-------------------ip:port : " + serviceAddress);
                }

                String[] addressArray = serviceAddress.split(":");
                String ip = addressArray[0];
                Integer port = Integer.valueOf(addressArray[1]);


                //创建RPC客户端
                RpcClient rpcClient = new RpcClient(ip, port);

                long startTime = System.currentTimeMillis();

                //发送请求
                XRpcResponse xRpcResponse = rpcClient.send(xRpcRequest);

                long endTime = System.currentTimeMillis();

                log.info("发送请求，获取到代理对象花费时间：" + (endTime - startTime));

                if (xRpcResponse == null) {
                    throw new RuntimeException("xRpcResponse is null");
                }

                if (StrUtil.isNotEmpty(xRpcResponse.getError())) {
                    throw new RuntimeException(xRpcResponse.getError());
                }

                return xRpcResponse.getResult();
            }
        };

        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class<?>[]{interfaceClass},invocationHandler);
    }

}
